package org.datascooter.cglib.proxy;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.datascooter.inface.IDataManager;
import org.datascooter.utils.TypeUtils;

public class WizardObjectInterceptor implements MethodInterceptor {

	private final IDataManager manager;
	protected Map<String, Object> valueMap = new HashMap<String, Object>();
	protected Map<String, WizardObjectInterceptor> childMap = new HashMap<String, WizardObjectInterceptor>();

	public WizardObjectInterceptor(IDataManager dataManager) {
		this.manager = dataManager;
	}

	public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		if (method.getReturnType().equals(void.class)) {
			return processSet(object, method, args, methodProxy);
		} else {
			return processGet(object, method, args, methodProxy);
		}
	}

	private Object processGet(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		Class<?> klazz = method.getReturnType();
		if (TypeUtils.isPrimitive(klazz)) {
			if (valueMap.containsKey(method.getName())) {
				return valueMap.get(method.getName());
			}
		} else {
			if (childMap.containsKey(method.getName())) {
				if (args.length == 0) {
					return Enhancer.create(klazz, childMap.get(method.getName()));
				} else if (args.length == 1) {
					return Enhancer.create(klazz, childMap.get(method.getName() + "_" + args[0]));
				}
			}
		}
		return methodProxy.invokeSuper(object, args);
	}

	private Object processSet(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		if (args.length == 1) {
			if (TypeUtils.isPrimitive(args[0].getClass())) {
				valueMap.put(method.getName(), args);
			} else {
				childMap.put(method.getName(), new WizardObjectInterceptor(manager));
			}
		} else if (args.length == 2) {
			if (TypeUtils.isPrimitive(args[1].getClass())) {
				valueMap.put(method.getName() + "_" + args[0], args[1]);
			} else {
				childMap.put(method.getName() + "_" + args[0], new WizardObjectInterceptor(manager));
			}
		}
		return null;
	}
}
